home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_11_08
/
weber
/
display.c
< prev
next >
Wrap
Text File
|
1993-03-11
|
32KB
|
794 lines
/***************************************************************
* file: DISPLAY.C
* purpose: display a PCX file
* contains:
* display_file() - displays a file.
* display_sample() - gets a pointer to a sample of the displayed file.
* copyright: 1993 by David Weber. All rights reserved.
* This software can be used for any purpose as object, library or executable.
* It cannot be sold for profit as source code.
* history:
* 02-26-93 - initial code, cobbled from various stuff
**************************************************************/
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include "gui.h"
#include "display.h"
#include "zone.h"
/* local prototypes */
static int get_pcx_header(int fh);
static unsigned int read_pcx(unsigned char *buffer,unsigned int number_of_bytes);
static unsigned int read_source_buffer(void);
static int open_scaler(int xscale,int yscale,DISPLAY_BOX *screen,DISPLAY_BOX *file);
static int scaler(unsigned char *buffer);
static void close_scaler(void);
static int open_sampler(DISPLAY_BOX *file);
static void get_sample(unsigned char *scaler_buffer,int ylines);
/* local data */
/* PCX */
static int src_fh; /* file handle of source */
static unsigned int bytes_per_line; /* byte width of image */
static unsigned int lines_per_page; /* pixel length of image */
static unsigned int src_bytes; /* byte count in buffer */
static unsigned int src_size; /* size of buffer */
static unsigned char *src_buffer; /* buffer pointer */
/* SCALER */
static unsigned char *scaler_buffer; /* buffer for scaler operations */
static int scaler_in_bytes_per_line; /* input bytes per line */
static int scaler_out_bytes_per_line; /* output bytes per line */
static int scaler_error; /* scaler y error */
static int scaler_delta; /* scale ratio delat error */
static unsigned int scaler_buffer_size; /* minimum buffer size */
static int scaler_lines; /* minimum lines in buffer */
static short *scaler_offset; /* offset from line start for scaler_mask */
static unsigned short *scaler_mask; /* bit mask of input line */
static int scaler_xscale; /* x scale value in fixed point .00 */
static int scaler_yscale; /* y scale value in fixed point .00 */
/* DISPLAY */
static unsigned char *display_buffers[MAX_DISPLAY_BUFFERS]; /* array of buffers for display */
static int display_buffer_count = 0; /* number of allocated buffers */
static int display_lines_per_buffer; /* number of lines in a buffer */
static int display_bytes_per_line; /* number of bytes in a display_buffer line */
static DISPLAY_BOX display_screen_box; /* screen info */
static NUMBERED_BOX *numbered_boxes = NULL; /* numbered boxes outside of image */
/* IMAGE SAMPLING */
static int xsample,ysample,xdelta,ydelta; /* scaled image dimensions */
static int sample_line; /* current sample line */
static unsigned char *display_sample_ptr = NULL; /* pointer to sampled image */
/************************************************
* function: int display_file(char *filename)
* Opens PCX file and displays same, displays error box
* if it fails
* parameters: pointer to file name
* returns: 1 if done or 0 if failed
************************************************/
int display_file(char *filename)
{
fg_box_t box;
DISPLAY_BOX screen;
int screen_aspect_ratio;
DISPLAY_BOX file;
int file_aspect_ratio;
int xscale,yscale,i,skip_it;
unsigned char *p;
if (display_buffer_count > 0)
{ /* clear out previous buffers */
for (i = 0 ; i < display_buffer_count ; i++)
free(display_buffers[i]);
display_buffer_count = 0;
}
if (display_sample_ptr != NULL)
free(display_sample_ptr);
screen.x = 0; /* size the display area on screen */
screen.y = 0;
screen.width = gui_screen_width;
screen.height = gui_screen_height - 2 * gui_char_height;
fg_make_box(box,0,0,screen.width-1,screen.height-1); /* clear screen */
fg_msm_hidecursor();
fg_fillbox(FG_BLACK,FG_MODE_SET,~0,box);
fg_msm_showcursor();
if ((src_buffer = (unsigned char *) malloc(PCX_READ_BUFFER)) == NULL)
{ /* file read buffer */
message_box("Out of memory.");
return 0;
}
if ((src_fh = open(filename,O_RDONLY | O_BINARY)) == -1) /* open file */
{
message_box("Cannot open file.");
free(src_buffer);
return 0;
}
if (!get_pcx_header(src_fh)) /* decode header */
{
message_box("Not a valid monochrome PCX file.");
free(src_buffer);
close(src_fh);
return 0;
} /* the following calculations are fixed point .00 */
screen_aspect_ratio = (int) (((long)gui_screen_width * 100L) / (long)gui_screen_height);
file.x = file.y = 0; /* display area of file */
file.width = bytes_per_line * 8;
file.height = lines_per_page;
file_aspect_ratio = (int) (((long)file.width * 100L) / (long)file.height);
if (file.width < screen.width || file.height < screen.height)
{ /* if it has to be scaled up, it has too little info for region finding */
message_box("PCX file too small for region finding.");
free(src_buffer);
close(src_fh);
return 0;
}
if (IDEAL_SCREEN_ASPECT > file_aspect_ratio)
{ /* y major scaling */
yscale = (int) (((long)file.height * 100L) / (long)screen.height);
xscale = (int) (((long)yscale * (long)IDEAL_SCREEN_ASPECT) / (long)screen_aspect_ratio);
screen.width = (int) (((long)file.width * 100L) / (long)xscale);
screen.x = (gui_screen_width - screen.width) / 2;
}
else
{ /* x major scaling */
xscale = (int) (((long)file.width * 100L) / (long)screen.width);
yscale = (int) (((long)xscale * (long)screen_aspect_ratio) / (long)IDEAL_SCREEN_ASPECT);
screen.height = (int) (((long)file.height * 100L) / (long)yscale);
screen.y = (gui_screen_height - 2 * gui_char_height - screen.height) / 2;
}
src_bytes = src_size = 0;
if (!open_scaler(xscale,yscale,&screen,&file)) /* set up scaler */
{
free(src_buffer);
close(src_fh);
message_box("Out of memory.");
return 0;
}
display_screen_box = screen; /* set up display parameters */
display_bytes_per_line = scaler_out_bytes_per_line;
display_screen_box.width = display_bytes_per_line * 8;
display_lines_per_buffer = DISPLAY_BUFFER_SIZE / display_bytes_per_line;
fg_make_box(box,screen.x,screen.y,screen.x+screen.width-1,screen.y+screen.height-1);
fg_msm_hidecursor();
fg_fillbox(FG_WHITE,FG_MODE_SET,~0,box); /* draw blank page */
fg_make_box(box,0,0,screen.width-1,0);
for (i = skip_it = 0 ; i < screen.height ; i++) /* scale file to screen */
{
if ((i % display_lines_per_buffer) == 0)
{ /* need another array */
if ((display_buffers[display_buffer_count] = (unsigned char *) malloc(DISPLAY_BUFFER_SIZE)) == NULL)
{
display_free();
close_scaler();
free(src_buffer);
close(src_fh);
fg_msm_showcursor();
message_box("Out of memory.");
return 0;
}
p = display_buffers[display_buffer_count];
display_buffer_count++;
}
if (skip_it)
memset(p,0,scaler_out_bytes_per_line);
else if (!scaler(p))
skip_it = 1;
fg_drawmatrix(FG_BLACK,FG_MODE_SET,~0,FG_ROT0,screen.x